/*
>> LUTNeighbourhoodToPixelOp.s
>>
>> LUT-based Neighbourhood operation skeleton, 
>>
>> Author: Wouter Caarls
>> Date:   06-04-2005
*/

#include "ilpstrategies.h"
#include "c/NeighbourhoodToPixelOp.s"

void setLUT(int x, int y, float val)
{
  lut[y+_lutsize/2][x+_lutsize/2] = val;
}

void LUTNeighbourhoodToPixelOp(argcode_t *argcode, int arguments, code body)
{
  int _lutsize, _ii;

  _lutsize = (@argcode[0].argid).data.d;

  for (_ii=0; _ii < arguments; _ii++)
  {
    if (argcode[_ii].argtype == ARG_SCALAR_IN)
    {
      /* Non-streams must be initialised */
      @declare(addrpointer(argcode[_ii].datatype), argcode[_ii].id);
      if (@dataclass(argcode[_ii].datatype) == DATACLASS_INTEGER)
        @argcode[_ii].id = &(@argcode[_ii].argid).data.d;
      else if (@dataclass(argcode[_ii].datatype) == DATACLASS_FLOAT)
        @argcode[_ii].id = &(@argcode[_ii].argid).data.f;
      else
        @argcode[_ii].id = cast(addpointer(argcode[_ii].datatype), (@argcode[_ii].argid).data.b);
    }
  }

  @declare2d(`float`, `lut`, _lutsize, _lutsize);

  /* Body initializes lookup table */
  @body;

  body = `{
  float acc;
  int x;
  int y;

  acc = 0;
  for (y=-_lutsize/2; y <= _lutsize/2; y++)
    for (x=-_lutsize/2; x <= _lutsize/2; x++)
      acc = acc + ($@(argcode[1].id))[y][x] * lut[y+_lutsize/2][x+_lutsize/2];

  *($@(argcode[2].id)) = acc;
  }`;

  for (_ii = 0; _ii < 2; _ii++)
  {
    argcode[1].extents[_ii].start = -_lutsize/2;
    argcode[1].extents[_ii].end = _lutsize/2;
    argcode[1].extents[_ii].size = _lutsize;
  }

  NeighbourhoodToPixelOp(argcode, arguments, body);
}
